import { WSClient } from '../core/ws-client';
import { AccountBalanceData, OrderParams, OrderResponse, WsRequest } from '../core/types';

export class PrivateService {
    private wsClient: WSClient;
    private defaultTimeout = 15000; // 默认超时时间：15秒

    constructor(client: WSClient) {
        this.wsClient = client;
    }

    /**
     * 订阅账户余额信息
     * @param onBalanceUpdate 当接收到余额更新时调用的回调函数
     * @param ccy 可选：指定币种，多个用逗号分隔
     * @param timeout 可选：超时时间（毫秒）
     * @returns Promise，在订阅成功或失败时解析
     */
    public subscribeAccountBalance(
        onBalanceUpdate: (balanceData: AccountBalanceData[]) => void,
        ccy?: string,
        timeout: number = this.defaultTimeout
    ): Promise<void> {
        return new Promise((resolve, reject) => {
            // 确保WebSocket已连接且已登录
            if (!this.wsClient.isConnected()) {
                reject(new Error("WebSocket is not connected"));
                return;
            }

            if (!this.wsClient.checkLoggedIn()) {
                reject(new Error("WebSocket is not logged in"));
                return;
            }

            // 设置超时
            const subscribeTimeout = setTimeout(() => {
                this.wsClient.off('subscribeSuccess', subscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error(`Subscribe to account balance timeout after ${timeout}ms`));
            }, timeout);

            // 注册回调函数，处理 'account' 频道的消息
            this.wsClient.on('account', (data: AccountBalanceData[]) => {
                console.log('Received account balance update');
                onBalanceUpdate(data);
            });

            // 监听订阅成功事件
            const subscribeSuccessHandler = (response: any) => {
                if (response.arg?.channel === 'account') {
                    clearTimeout(subscribeTimeout);
                    resolve();
                }
            };

            // 监听错误事件
            const errorHandler = (err: any) => {
                clearTimeout(subscribeTimeout);
                if (err.message?.includes('account') || err.code) {
                    reject(err);
                }
            };

            this.wsClient.once('subscribeSuccess', subscribeSuccessHandler);
            this.wsClient.once('error', errorHandler);

            // 发送订阅请求
            const subscribeSuccess = this.wsClient.subscribe('account', undefined, ccy);
            if (!subscribeSuccess) {
                clearTimeout(subscribeTimeout);
                this.wsClient.off('subscribeSuccess', subscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error("Failed to send subscription request"));
            }
        });
    }

    /**
     * 取消订阅账户余额信息
     * @param ccy 可选：指定币种，多个用逗号分隔
     * @param timeout 可选：超时时间（毫秒）
     * @returns Promise，在取消订阅成功或失败时解析
     */
    public unsubscribeAccountBalance(
        ccy?: string,
        timeout: number = this.defaultTimeout
    ): Promise<void> {
        return new Promise((resolve, reject) => {
            // 设置超时
            const unsubscribeTimeout = setTimeout(() => {
                this.wsClient.off('unsubscribeSuccess', unsubscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error(`Unsubscribe from account balance timeout after ${timeout}ms`));
            }, timeout);

            // 监听取消订阅成功事件
            const unsubscribeSuccessHandler = (response: any) => {
                if (response.arg?.channel === 'account') {
                    clearTimeout(unsubscribeTimeout);
                    resolve();
                }
            };

            // 监听错误事件
            const errorHandler = (err: any) => {
                clearTimeout(unsubscribeTimeout);
                if (err.message?.includes('account') || err.code) {
                    reject(err);
                }
            };

            this.wsClient.once('unsubscribeSuccess', unsubscribeSuccessHandler);
            this.wsClient.once('error', errorHandler);

            // 发送取消订阅请求
            const unsubscribeSuccess = this.wsClient.unsubscribe('account', undefined, ccy);
            if (!unsubscribeSuccess) {
                clearTimeout(unsubscribeTimeout);
                this.wsClient.off('unsubscribeSuccess', unsubscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error("Failed to send unsubscription request"));
            }
        });
    }

    /**
     * 下单
     * @param orderParams 订单参数
     * @param timeout 可选：超时时间（毫秒）
     * @returns Promise，在下单成功或失败时解析
     */
    public placeOrder(
        orderParams: OrderParams,
        timeout: number = this.defaultTimeout
    ): Promise<OrderResponse> {
        return new Promise((resolve, reject) => {
            // 确保WebSocket已连接且已登录
            if (!this.wsClient.isConnected()) {
                reject(new Error("WebSocket is not connected"));
                return;
            }

            if (!this.wsClient.checkLoggedIn()) {
                reject(new Error("WebSocket is not logged in"));
                return;
            }

            // 生成唯一请求ID
            const requestId = `order_${Date.now()}`;

            // 构建下单请求
            const orderRequest: WsRequest<OrderParams> = {
                id: requestId,
                op: 'order',
                args: [orderParams]
            };

            // 监听响应
            const responseHandler = (response: OrderResponse) => {
                if (response.data && response.data.length > 0) {
                    if (response.data[0].sCode === '0') {
                        resolve(response);
                    } else {
                        reject(new Error(`Order failed: ${response.data[0].sMsg} (Code: ${response.data[0].sCode})`));
                    }
                } else {
                    reject(new Error("Invalid order response"));
                }
            };

            // 监听错误
            const errorHandler = (err: any) => {
                reject(err);
            };

            // 设置超时
            const orderTimeout = setTimeout(() => {
                this.wsClient.off(`response:${requestId}`, responseHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error(`Order request timeout after ${timeout}ms`));
            }, timeout);

            // 注册响应处理器
            this.wsClient.once(`response:${requestId}`, (response: OrderResponse) => {
                clearTimeout(orderTimeout);
                this.wsClient.off('error', errorHandler);
                responseHandler(response);
            });

            this.wsClient.once('error', (err: any) => {
                clearTimeout(orderTimeout);
                this.wsClient.off(`response:${requestId}`, responseHandler);
                errorHandler(err);
            });

            // 发送请求
            const sendSuccess = this.wsClient.send(orderRequest);
            if (!sendSuccess) {
                clearTimeout(orderTimeout);
                this.wsClient.off(`response:${requestId}`, responseHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error("Failed to send order request"));
            }
        });
    }

    /**
     * 订阅订单更新
     * @param onOrderUpdate 当接收到订单更新时调用的回调函数
     * @param instType 可选：产品类型
     * @param timeout 可选：超时时间（毫秒）
     * @returns Promise，在订阅成功或失败时解析
     */
    public subscribeOrders(
        onOrderUpdate: (orderData: any) => void,
        instType?: string,
        timeout: number = this.defaultTimeout
    ): Promise<void> {
        return new Promise((resolve, reject) => {
            // 确保WebSocket已连接且已登录
            if (!this.wsClient.isConnected()) {
                reject(new Error("WebSocket is not connected"));
                return;
            }

            if (!this.wsClient.checkLoggedIn()) {
                reject(new Error("WebSocket is not logged in"));
                return;
            }

            // 设置超时
            const subscribeTimeout = setTimeout(() => {
                this.wsClient.off('subscribeSuccess', subscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error(`Subscribe to orders timeout after ${timeout}ms`));
            }, timeout);

            // 注册回调函数，处理 'orders' 频道的消息
            this.wsClient.on('orders', onOrderUpdate);

            // 监听订阅成功事件
            const subscribeSuccessHandler = (response: any) => {
                if (response.arg?.channel === 'orders') {
                    clearTimeout(subscribeTimeout);
                    resolve();
                }
            };

            // 监听错误事件
            const errorHandler = (err: any) => {
                clearTimeout(subscribeTimeout);
                if (err.message?.includes('orders') || err.code) {
                    reject(err);
                }
            };

            this.wsClient.once('subscribeSuccess', subscribeSuccessHandler);
            this.wsClient.once('error', errorHandler);

            // 发送订阅请求
            const subscribeSuccess = this.wsClient.subscribe('orders', instType);
            if (!subscribeSuccess) {
                clearTimeout(subscribeTimeout);
                this.wsClient.off('subscribeSuccess', subscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error("Failed to send subscription request"));
            }
        });
    }

    /**
     * 取消订阅订单更新
     * @param instType 可选：产品类型
     * @param timeout 可选：超时时间（毫秒）
     * @returns Promise，在取消订阅成功或失败时解析
     */
    public unsubscribeOrders(
        instType?: string,
        timeout: number = this.defaultTimeout
    ): Promise<void> {
        return new Promise((resolve, reject) => {
            // 设置超时
            const unsubscribeTimeout = setTimeout(() => {
                this.wsClient.off('unsubscribeSuccess', unsubscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error(`Unsubscribe from orders timeout after ${timeout}ms`));
            }, timeout);

            // 监听取消订阅成功事件
            const unsubscribeSuccessHandler = (response: any) => {
                if (response.arg?.channel === 'orders') {
                    clearTimeout(unsubscribeTimeout);
                    resolve();
                }
            };

            // 监听错误事件
            const errorHandler = (err: any) => {
                clearTimeout(unsubscribeTimeout);
                if (err.message?.includes('orders') || err.code) {
                    reject(err);
                }
            };

            this.wsClient.once('unsubscribeSuccess', unsubscribeSuccessHandler);
            this.wsClient.once('error', errorHandler);

            // 发送取消订阅请求
            const unsubscribeSuccess = this.wsClient.unsubscribe('orders', instType);
            if (!unsubscribeSuccess) {
                clearTimeout(unsubscribeTimeout);
                this.wsClient.off('unsubscribeSuccess', unsubscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error("Failed to send unsubscription request"));
            }
        });
    }
} 